/*******************************************************************************
 *                                 AWorks
 *                       ----------------------------
 *                       innovating embedded platform
 *
 * Copyright (c) 2001-present Guangzhou ZHIYUAN Electronics Co., Ltd.
 * ALL rights reserved.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *
 * The License of this software follows LGPL v2.1, See the LICENSE for more details:
 * https://opensource.org/licenses/LGPL-2.1
 *
 * Contact information:
 * web site:    http://www.zlg.cn/
 *******************************************************************************/

#ifndef HPM_ROMAPI_H
#define HPM_ROMAPI_H

#include "common/hpm_common.h"
#include "core/include/hpm6e00_regs_base.h"
#include "driver/romapi/hpm_romapi_xpi_def.h"
#include "driver/romapi/hpm_romapi_xpi_nor_def.h"
#include "driver/romapi/hpm_romapi_xpi_soc_def.h"
#include "driver/romapi/hpm_romapi_xpi_ram_def.h"

#define AES_BLOCK_SIZE (16U)     /**< AES block size in bytes */

typedef uint32_t hpm_stat_t;

/**
 * @brief SDP packet data structure
 */
typedef struct _sdp_packet_struct {
    struct _sdp_packet_struct *next_cmd;
    union {
        struct {
            uint32_t RESERVED0 : 1;
            uint32_t PKTINT : 1;     /**< Packet interrupt flag */
            uint32_t DCRSEMA : 1;    /**< Descrement Semaphore flag */
            uint32_t CHAIN : 1;      /**< Chain Packet flag */
            uint32_t HASHINIT : 1;   /**< Hash initialize flag */
            uint32_t HASHFINISH : 1; /**< Hash finish flag */
            uint32_t CIPHIV : 1;     /**< Cipher IV flag */
            uint32_t RESERVED1 : 17;
            uint32_t PKTTAG : 8;     /**< Packet tag flag, not used */
        };
        uint32_t PKT_CTRL;           /**< Packet control word */
    } pkt_ctrl;
    uint32_t src_addr;               /**< Source address */
    uint32_t dst_addr;               /**< Destination address */
    uint32_t buf_size;               /**< Data buffer size in bytes */
    uint32_t reserved[3];
} sdp_pkt_struct_t;

/**
 * @brief SDP AES key bit options
 */
typedef enum {
    sdp_aes_keybits_128, /**< 128 bit AES key */
    sdp_aes_keybits_256, /**< 256 bit AES key */
} sdp_aes_key_bits_t;

/**
 * @brief SDP AES context structure
 */
typedef struct {
    uint8_t          key_idx;                                 /**< AES key index */
    uint8_t          key_bits;                                /**< AES key bits */
    uint16_t         reserved;
    sdp_pkt_struct_t sdp_pkt;                                 /**< SDP packet for AES operation */
    uint32_t         buf0[AES_BLOCK_SIZE / sizeof(uint32_t)]; /**< buf0 */
    uint32_t         buf1[AES_BLOCK_SIZE / sizeof(uint32_t)]; /**< buf1 */
    uint32_t         buf2[AES_BLOCK_SIZE / sizeof(uint32_t)]; /**< buf2 */
    uint32_t         buf3[AES_BLOCK_SIZE / sizeof(uint32_t)]; /**< buf3 */
} sdp_aes_ctx_t;

/**
 * @brief AES operation option
 */
typedef enum {
    sdp_aes_op_encrypt, /**< AES Encrypt operation */
    sdp_aes_op_decrypt, /**< AES Decrypt operation */
} sdp_aes_op_t;

/**
 * @brief SDP HASH algorithm definitions
 */
typedef enum {
    sdp_hash_alg_sha1,   /**< SDP SHA1 */
    sdp_hash_alg_crc32,  /**< SDP CRC32 */
    sdp_hash_alg_sha256, /**< SDP SHA256 */
    sdp_hash_alg_max = sdp_hash_alg_sha256,
} sdp_hash_alg_t;

/**
 * @brief SDP DMA context
 */
typedef struct {
    sdp_pkt_struct_t sdp_pkt; /**< SDP packet for DMA operation (memset/memcpy) */
} sdp_dma_ctx_t;

/**
 * @brief SDP HASH context
 */
typedef struct {
    sdp_pkt_struct_t sdp_pkt;       /**< SDP packet for HASH operation */
    uint32_t         internal[64];  /**< internal buffer */
} sdp_hash_ctx_t;

/* \brief OTP 段定义*/
typedef enum {
    otp_region0_mask = 1U,  /* 地址范围：[0, 7]  */
    otp_region1_mask = 2U,  /* 地址范围：[8, 15] */
    otp_region2_mask = 4U,  /* 地址范围：[16, 127] */
    otp_region3_mask = 8U,  /* 地址范围：用户定义 */
} otp_region_t;

/* \brief OTP 锁可选项*/
typedef enum {
    otp_no_lock           = 0,
    otp_read_only         = 1,
    otp_permanent_no_lock = 2,
    otp_disable_access    = 3,
    otp_lock_option_max   = otp_disable_access,
} otp_lock_option_t;

/* \brief OTP 驱动接口*/
typedef struct {
    uint32_t    version;                                                               /* OTP 驱动接口版本 */
    void       (*init)(void);                                                          /* 初始化 */
    void       (*deinit)(void);                                                        /* 反初始化 */
    uint32_t   (*read_from_shadow)(uint32_t addr);                                     /**< OTP driver interface: read from shadow */
    uint32_t   (*read_from_ip)(uint32_t addr);                                         /**< OTP driver interface: read from ip */
    hpm_stat_t (*program)(uint32_t addr, const uint32_t *src, uint32_t num_of_words);  /* 编程接口 */
    hpm_stat_t (*reload)(otp_region_t region);                                         /**< OTP driver interface: reload */
    hpm_stat_t (*lock)(uint32_t addr, otp_lock_option_t lock_option);                  /**< OTP driver interface: lock */
    hpm_stat_t (*lock_shadow)(uint32_t addr, otp_lock_option_t lock_option);           /**< OTP driver interface: lock_shadow */
    hpm_stat_t (*set_configurable_region)(uint32_t start, uint32_t num_of_words);      /**< OTP driver interface: set_configurable_region */
    hpm_stat_t (*write_shadow_register)(uint32_t addr, uint32_t data);                 /**< OTP driver interface: write_shadow_register */
} otp_driver_interface_t;

/* \brief XPI 驱动接口*/
typedef struct {
    uint32_t     version;                                                                                             /* XPI 驱动接口版本 */
    hpm_stat_t (*get_default_config)(xpi_config_t *xpi_config);                                                       /* 获取默认配置 */
    hpm_stat_t (*get_default_device_config)(xpi_device_config_t *dev_config);                                         /* 获取默认设备配置 */
    hpm_stat_t (*init)(XPI_Type *base, xpi_config_t *xpi_config);                                                     /**< XPI driver interface: initialize the XPI using xpi_config */
    hpm_stat_t (*config_ahb_buffer)(XPI_Type *base, xpi_ahb_buffer_cfg_t *ahb_buf_cfg);                               /* 配置 AHB 缓存 */
    hpm_stat_t (*config_device)(XPI_Type *base, xpi_device_config_t *dev_cfg, xpi_channel_t channel);                 /* 配置设备 */
    hpm_stat_t (*update_instr_table)(XPI_Type *base, const uint32_t *inst_base, uint32_t seq_idx, uint32_t num);      /* 更新指令表 */
    hpm_stat_t (*transfer_blocking)(XPI_Type *base, xpi_xfer_ctx_t *xfer);                                            /* transfer command/data using block interface */
    void       (*software_reset)(XPI_Type *base);                                                                     /**< Software reset the XPI controller */
    bool_t     (*is_idle)(XPI_Type *base);                                                                            /**< XPI driver interface: Check whether IP is idle */
    void       (*update_dllcr)(XPI_Type *base, uint32_t serial_root_clk_freq,
    		                   uint32_t data_valid_time, xpi_channel_t channel,
                               uint32_t dly_target);                                                                  /**< XPI driver interface: update delay line setting */
    hpm_stat_t (*get_abs_apb_xfer_addr)(XPI_Type *base, xpi_xfer_channel_t channel,
    		                            uint32_t in_addr, uint32_t *out_addr);                                        /**< XPI driver interface: Get absolute address for APB transfer */
} xpi_driver_interface_t;

/* \brief XPI NOR 驱动接口*/
typedef struct {
    uint32_t     version;                                                    /* XPI NOR 驱动接口版本 */
    hpm_stat_t (*get_config)(XPI_Type                *base,
    		                 xpi_nor_config_t        *nor_cfg,
							 xpi_nor_config_option_t *cfg_option);           /* 获取 FLASH 配置 */
    hpm_stat_t (*init)(XPI_Type *base, xpi_nor_config_t *nor_config);        /* FLASH 初始化 */
    hpm_stat_t (*enable_write)(XPI_Type               *base,
    		                   xpi_xfer_channel_t      channel,
							   const xpi_nor_config_t *nor_config,
							   uint32_t                addr);                /* FLASH 写使能 */
    hpm_stat_t (*get_status)(XPI_Type               *base,
    		                 xpi_xfer_channel_t      channel,
							 const xpi_nor_config_t *nor_config,
							 uint32_t                addr,
                             uint16_t               *out_status);            /* 获取 FLASH 状态寄存器*/
    hpm_stat_t (*wait_busy)(XPI_Type               *base,
    		                xpi_xfer_channel_t      channel,
							const xpi_nor_config_t *nor_config,
							uint32_t                addr);                   /* FLASH 忙等待*/
    hpm_stat_t (*erase)(XPI_Type               *base,
    		            xpi_xfer_channel_t      channel,
						const xpi_nor_config_t *nor_config,
						uint32_t                start,
                        uint32_t                length);                     /* 擦除 FLASH 特定段 */
    hpm_stat_t (*erase_chip)(XPI_Type               *base,
    		                 xpi_xfer_channel_t      channel,
							 const xpi_nor_config_t *nor_config);            /* 擦除整个 FLASH */
    hpm_stat_t (*erase_sector)(XPI_Type               *base,
    		                   xpi_xfer_channel_t      channel,
							   const xpi_nor_config_t *nor_config,
							   uint32_t                addr);                /* 擦除 FLASH 特定扇区 */
    hpm_stat_t (*erase_block)(XPI_Type               *base,
    		                  xpi_xfer_channel_t      channel,
							  const xpi_nor_config_t *nor_config,
							  uint32_t                addr);                 /* 擦除 FLASH 特定块 */
    hpm_stat_t (*program)(XPI_Type               *base,
    		              xpi_xfer_channel_t      channel,
						  const xpi_nor_config_t *nor_config,
						  const uint32_t         *src,
                          uint32_t                dst_addr,
						  uint32_t                length);                   /* 编程数据到 FLASH 特定的地址 */
    hpm_stat_t (*read)(XPI_Type               *base,
    		           xpi_xfer_channel_t      channel,
					   const xpi_nor_config_t *nor_config,
					   uint32_t               *dst,
                       uint32_t                start,
					   uint32_t                length);                       /* 从 FLASH 特定的地址读数据 */
    hpm_stat_t (*page_program_nonblocking)(XPI_Type               *base,
    		                               xpi_xfer_channel_t      channel,
										   const xpi_nor_config_t *nor_config,
                                           const uint32_t         *src,
										   uint32_t                dst_addr,
										   uint32_t                length);   /* 用非阻塞接口编程 FLASH 页 */
    hpm_stat_t (*erase_sector_nonblocking)(XPI_Type               *base,
    		                               xpi_xfer_channel_t      channel,
										   const xpi_nor_config_t *nor_config,
                                           uint32_t                addr);     /* 用非阻塞接口擦除 FLASH 扇区 */
    hpm_stat_t (*erase_block_nonblocking)(XPI_Type               *base,
    		                              xpi_xfer_channel_t      channel,
										  const xpi_nor_config_t *nor_config,
                                          uint32_t                addr);      /* 用非阻塞接口擦除 FLASH 块 */
    /**< XPI NOR driver interface: erase the whole FLASh using nonblocking interface */
    hpm_stat_t (*erase_chip_nonblocking)(XPI_Type               *base,
    		                             xpi_xfer_channel_t      channel,
										 const xpi_nor_config_t *nor_config); /* 用非阻塞接口擦除整个 FLASH */
    uint32_t     reserved0[3];
    hpm_stat_t (*auto_config)(XPI_Type                *base,
    		                  xpi_nor_config_t        *nor_cfg,
							  xpi_nor_config_option_t *cfg_option);           /* 基于 cfg_option 设置自动配置 FLASH */
    hpm_stat_t (*get_property)(XPI_Type         *base,
    		                   xpi_nor_config_t *nor_cfg,
							   uint32_t          property_id,
							   uint32_t         *value);                      /**< XPI NOR driver interface: Get FLASH properties */

} xpi_nor_driver_interface_t;

/* \brief xpi ram 驱动接口*/
typedef struct {
    uint32_t     version;                                           /* XPI RAM 驱动接口版本 */
    hpm_stat_t (*get_config)(XPI_Type                *base,
    		                 xpi_ram_config_t        *ram_cfg,
							 xpi_ram_config_option_t *cfg_option);  /**< Get XPI RAM configuration based on cfg_option */
    hpm_stat_t (*init)(XPI_Type *base, xpi_ram_config_t *ram_cfg);  /**< XPI RAM driver interface: Initialize XPI RAM */
} xpi_ram_driver_interface_t;

/* \brief sdp 驱动接口 */
typedef struct {
    /**< SDP API interface: API version */
    uint32_t version;
    /**< SDP API interface: Initialize IP */
    hpm_stat_t (*sdp_ip_init)(void);
    /**< SDP API interface: Deinitialize IP */
    hpm_stat_t (*sdp_ip_deinit)(void);
    /**< SDP API interface: Set AES key */
    hpm_stat_t (*aes_set_key)(sdp_aes_ctx_t *aes_ctx, const uint8_t *key, sdp_aes_key_bits_t keybits, uint32_t key_idx);
    /**< SDP API interface: AES ECB crypto operation */
    hpm_stat_t (*aes_crypt_ecb)(sdp_aes_ctx_t *aes_ctx, sdp_aes_op_t op, uint32_t len, const uint8_t *in, uint8_t *out);
    /**< SDP API interface: AES CBC crypto operation */
    hpm_stat_t (*aes_crypt_cbc)(sdp_aes_ctx_t *aes_ctx, sdp_aes_op_t op, uint32_t length, uint8_t iv[16],
                                const uint8_t *input, uint8_t *output);
    /**< SDP API interface: AES CTR crypto operation */
    hpm_stat_t (*aes_crypt_ctr)(sdp_aes_ctx_t *aes_ctx, uint8_t *nonce_ctr, uint8_t *input, uint8_t *output,
                                uint32_t length);
    /**< SDP API interface: AES CCM encryption */
    hpm_stat_t (*aes_ccm_gen_enc)(sdp_aes_ctx_t *aes_ctx, uint32_t input_len, const uint8_t *nonce, uint32_t nonce_len,
                                  const uint8_t *aad, uint32_t aad_len, const uint8_t *input, uint8_t *output,
                                  uint8_t *tag, uint32_t tag_len);
    /**< SDP API interface: AES CCM Decrypt and verify */
    hpm_stat_t (*aes_ccm_dec_verify)(sdp_aes_ctx_t *aes_ctx, uint32_t input_len, const uint8_t *nonce,
                                     uint32_t nonce_len, const uint8_t *aad, uint32_t aad_len, const uint8_t *input,
                                     uint8_t *output, const uint8_t *tag, uint32_t tag_len);
    /**< SDP API interface: memcpy */
    hpm_stat_t (*memcpy)(sdp_dma_ctx_t *dma_ctx, void *dst, const void *src, uint32_t length);
    /**< SDP API interface: memset */
    hpm_stat_t (*memset)(sdp_dma_ctx_t *dma_ctx, void *dst, uint8_t pattern, uint32_t length);
    /**< SDP API interface: HASH initialization */
    hpm_stat_t (*hash_init)(sdp_hash_ctx_t *hash_ctx, sdp_hash_alg_t alg);
    /**< SDP API interface: HASH update */
    hpm_stat_t (*hash_update)(sdp_hash_ctx_t *hash_ctx, const uint8_t *data, uint32_t length);
    /**< SDP API interface: HASH finish */
    hpm_stat_t (*hash_finish)(sdp_hash_ctx_t *hash_ctx, uint8_t *digest);
} sdp_driver_interface_t;

/* \brief Bootloader API 表*/
typedef struct {
    uint32_t                    version;                        /* Bootloader API 表版本 */
    char                       *copyright;                      /* copyright 字符串地址 */
    hpm_stat_t                (*run_bootloader)(void *arg);     /* bootloader 运行 API */
    otp_driver_interface_t     *otp_driver_if;                  /* otp 驱动接口地址 */
    xpi_driver_interface_t     *xpi_driver_if;                  /* xpi 驱动接口地址 */
    xpi_nor_driver_interface_t *xpi_nor_driver_if;              /* xpi nor 驱动接口地址 */
    xpi_ram_driver_interface_t *xpi_ram_driver_if;              /* xpi ram 驱动接口地址 */
    sdp_driver_interface_t     *sdp_driver_if;                  /* sdp 驱动接口地址 */
} bootloader_api_table_t;

/* \brief HPM Bootloader API 表地址*/
#define ROM_API_TABLE_ROOT ((const bootloader_api_table_t*)0x2001FF00U)

#ifdef __cplusplus
extern "C" {
#endif

/**
 * \brief 进入特定的 Boot 模式
 *
 * \param[in] ctx 进入 Bootloader 环境
 *
 * \retval
 */
static inline hpm_stat_t rom_enter_bootloader(void *ctx){
    return (hpm_stat_t)ROM_API_TABLE_ROOT->run_bootloader(ctx);
}

#ifdef __cplusplus
}
#endif

#define HPM_XPI0 ((XPI_Type *)HPM_XPI0_BASE)

#endif /* HPM_ROMAPI_H */

